package com.goldcn.sms.service;

import com.goldcn.Interceptor.SystemContext;
import com.goldcn.common.AliHttpUtils;
import com.goldcn.common.HttpUtil;
import com.goldcn.common.SmsTempEnum;
import com.goldcn.common.model.DataResult;
import com.goldcn.common.util.CommonUtils;
import com.goldcn.common.util.IdGen;
import com.goldcn.config.SmsConfig;
import com.goldcn.enumType.DataResultEnum;
import com.goldcn.sms.modle.SmsCommont;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.taobao.api.DefaultTaobaoClient;
import com.taobao.api.TaobaoClient;
import com.taobao.api.request.AlibabaAliqinFcSmsNumSendRequest;
import com.taobao.api.response.AlibabaAliqinFcSmsNumSendResponse;
import net.sf.json.JSONObject;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Created by kylin.woo on 3/11/2016.
 */

@Service("smsService")
public class SmsService {

    private static Logger log = LoggerFactory.getLogger(SmsService.class);
    @Autowired
    RedisTemplate redisTemplate;
    //验证码过期时间10分钟
    private static final int time = 10;
    @Autowired
    SmsConfig smsConfig;

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    CommentRepository commentRepository;

    @Autowired
    private MongoTemplate mongoTemplate;

    public Object sendSms(String mobile, HttpServletRequest request) throws Exception {
        String code = generateRamdomNum();
        log.info("mobile:{} code:{} ", mobile, code);
        redisTemplate.opsForValue().set(mobile, code);
        redisTemplate.expire(mobile, time, TimeUnit.MINUTES);
        return aliSend(mobile, code);
    }

    public Object aliSend(String tel, String code) throws Exception {

        DataResult<Map<String, String>> data_ext = HttpUtil.httpGet(smsConfig.getBaseService() + "/sysConfig/selectAllExtByCID?companyInfoID=" + SystemContext.getCompanyID(), restTemplate);
        Map<String, String> ext = new HashMap<String, String>();
        if (1 == data_ext.getIsSuccess()) {
            ext = data_ext.getData();
        }
        boolean sendEnable = false;
        if (ext.containsKey("noticeSMS") && ext.get("noticeSMS") != null && "1".equalsIgnoreCase(ext.get("noticeSMS").trim())) {
            sendEnable = true;
        }
        if (!sendEnable) {
            log.error("该公司短信没有开通，请检查配置参数noticeSMS,当前companyid=" + SystemContext.getCompanyID());
            return DataResultEnum.ERROR.getValue();
        }
        TaobaoClient client = new DefaultTaobaoClient(ext.get("aliUrl"), ext.get("appkey"), ext.get("secret"));
        log.info(SmsTempEnum.CHECK_CODE.getCode() + "");
        DataResult<Map<String, String>> data_temp = HttpUtil.httpGet(smsConfig.getBaseService() + "/sysConfig/selectTempByType?companyInfoID=" + SystemContext.getCompanyID() + "&type=" + SmsTempEnum.CHECK_CODE.getCode(), restTemplate);

        Map<String, String> temp = new HashMap<String, String>();
        if (1 == data_temp.getIsSuccess()) {
            temp = data_temp.getData();
        }
        log.info(ext.get("aliUrl") + "==" + ext.get("appkey") + "==" + ext.get("secret") + "== " + temp.get("smsFreeSignName").trim() + "==" + temp.get("smsTemplateCode"));
        //log.info(smsConfig.getAliUrl()+"=="+smsConfig.getAppkey()+"=="+smsConfig.getSecret()+"== "+smsConfig.getSmsFreeSignName()+"=="+smsConfig.getCodeTemplate());
        String smsFreeSignName = new String(temp.get("smsFreeSignName").trim());
        AlibabaAliqinFcSmsNumSendRequest req = new AlibabaAliqinFcSmsNumSendRequest();
        req.setSmsType("normal");
        req.setSmsFreeSignName(smsFreeSignName);
        // 多参数 "{\"code\":\""+code+"\",\"product\":\""+type+"\"}"
        req.setSmsParamString("{code:'" + code + "'}");
        req.setRecNum(tel);
        req.setSmsTemplateCode(temp.get("smsTemplateCode"));
        AlibabaAliqinFcSmsNumSendResponse rsp = client.execute(req);

        saveSms(req, SmsTempEnum.CHECK_CODE.getCode());

        if (rsp.getBody().indexOf("error_response") > 1) {
            return DataResultEnum.ERROR.getValue();
        }


        return DataResultEnum.SUCC.getValue();
    }


    /**
     * 发送短信通知
     *
     * @param tele       接收的手机号
     * @param type       模版类型（1验证码2下单通知3发货通知），阿里大于分配的 . eg:{"tempid":"SMS_56100004","param":"order,date"}
     * @param paraValues 参数值
     * @return
     * @author pengzh
     * @date 2017-3-16
     */
    public DataResult aliSendNoticeSMS(String tele, String type, String[] paraValues) {
        DataResult<Map<String, String>> data_ext = HttpUtil.httpGet(smsConfig.getBaseService() + "/sysConfig/selectAllExtByCID?companyInfoID=" + SystemContext.getCompanyID(), restTemplate);
        Map<String, String> ext = new HashMap<String, String>();
        if (1 == data_ext.getIsSuccess()) {
            ext = data_ext.getData();
        }
        boolean sendEnable = false;
        if (ext.containsKey("noticeSMS") && ext.get("noticeSMS") != null && "1".equalsIgnoreCase(ext.get("noticeSMS").trim())) {
            sendEnable = true;
        }
        if (!sendEnable) {
            log.error("该公司短信没有开通，请检查配置参数noticeSMS,当前companyid=" + SystemContext.getCompanyID());
            return DataResultEnum.ERROR.getValue();
        }
        DataResult<Map<String, String>> data_temp = HttpUtil.httpGet(smsConfig.getBaseService() + "/sysConfig/selectTempByType?companyInfoID=" + SystemContext.getCompanyID() + "&type=" + type, restTemplate);
        Map<String, String> template = new HashMap<String, String>();
        if (1 == data_temp.getIsSuccess()) {
            template = data_temp.getData();
        }
        String tempName = null;
        String para = "";
        try {
            tempName = template.get("smsTemplateCode");
            para = template.get("smsTempContext");
            if (tempName == null) {
                log.error("alidayu notice template fail:通知短信模版匹配不上，请检查阿里的配置，指定的模版编号:" + tempName);
                return DataResultEnum.ERROR.getValue();
            }
            String[] temps = para.split(",");
            if (para.length() < 1) {
                temps = new String[]{};
            }
            if (paraValues != null && para != null && paraValues.length > 0 && temps.length != paraValues.length) {
                log.error("alidayu notice template fail:通知短信模版形参与实参不一致,参数值:" + paraValues);
                return DataResultEnum.ERROR.getValue();
            }

            //阿里参数格式："{code:'" + code + "'}"
            String temp = "{";
            for (int i = 0; i < temps.length; i++) {
                temp += temps[i] + ":'" + paraValues[i] + "',";
            }

            //组成阿里参数格式
            para = temp.substring(0, temp.length() - 1) + "}";
            if (paraValues.length <= 0) {
                para = "{}";
            }
        } catch (Exception e) {
            log.error("alidayu notice template fail", e);
            return DataResultEnum.ERROR.getValue();
        }

        String smsFreeSignName = new String(template.get("smsFreeSignName").trim());
        TaobaoClient client = new DefaultTaobaoClient(ext.get("aliUrl"), ext.get("appkey"), ext.get("secret"));
        AlibabaAliqinFcSmsNumSendRequest req = new AlibabaAliqinFcSmsNumSendRequest();
        req.setSmsType("normal");
        req.setSmsFreeSignName(smsFreeSignName);
        // 多参数 "{\"code\":\""+code+"\",\"product\":\""+type+"\"}"
        req.setSmsParamString(para);
        req.setRecNum(tele);
        req.setSmsTemplateCode(tempName);

        try {
            AlibabaAliqinFcSmsNumSendResponse rsp = client.execute(req);
            if (rsp.getBody().indexOf("error_response") > 1) {
                return DataResultEnum.ERROR.getValue();
            }
            saveSms(req, Integer.parseInt(type));
        } catch (Exception e) {
            return DataResultEnum.ERROR.getValue();
        }
        return DataResultEnum.SUCC.getValue();
    }


    /**
     * 银行卡234要素验证
     *
     * @param userName
     * @param bankCard
     * @param idCard
     * @param userMobile
     * @return
     */
    public Object aliVerifyBankCard(String userName, String bankCard, String idCard, String userMobile) {
        String appCode = null;
        DataResult<Map<String, String>> data_ext = HttpUtil.httpGet(smsConfig.getBaseService() + "/sysConfig/selectAllExtByCID?companyInfoID=" + SystemContext.getCompanyID(), restTemplate);
        Map<String, String> ext = new HashMap<String, String>();
        if (1 == data_ext.getIsSuccess()) {
            ext = data_ext.getData();
        }
        boolean sendEnable = false;
        if (ext.containsKey("bankAuthFlag") && ext.get("bankAuthFlag") != null && "1".equalsIgnoreCase(ext.get("bankAuthFlag").trim())) {
            sendEnable = true;
        }
        if (!sendEnable) {
            log.error("该公司银行卡验证没有开通，请检查配置参数:bankAuthFlag,当前companyid=" + SystemContext.getCompanyID());
            return DataResultEnum.ERROR.getValue();
        }
        if (ext.containsKey("bankAuthAppCode") && ext.get("bankAuthAppCode") != null && ext.get("bankAuthAppCode").trim().length() > 1) {
            appCode = ext.get("bankAuthAppCode");
        }
        if (null == appCode) {
            log.error("该公司银行卡验证参数设置为空，请检查配置参数:bankAuthAppCode,当前companyid=" + SystemContext.getCompanyID());
            return DataResultEnum.ERROR.getValue();
        }
        String host = "http://yunyidata.market.alicloudapi.com";
        String path = "/bankAuthenticate4";
        String method = "POST";
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Authorization", "APPCODE " + appCode);
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put("ReturnBankInfo", "YES");
        bodys.put("cardNo", bankCard);
        bodys.put("idNo", idCard);
        bodys.put("name", userName);
        bodys.put("phoneNo", userMobile);

        try {

            HttpResponse response = AliHttpUtils.doPost(host, path, method, headers, querys, bodys);
            String bankTemp = EntityUtils.toString(response.getEntity());

            JSONObject json = JSONObject.fromObject(bankTemp);

            Map<String, Object> result = new HashMap<String, Object>();
            result.put("message", json.optString("respMessage", ""));
            if (json.optString("respCode", "").equalsIgnoreCase("0000")) {
                result.put("code", 1);
            } else {
                result.put("code", 0);
            }
            return result;
        } catch (Exception e) {
            log.error("调用第三方银行卡验证失败，当前companyid=" + SystemContext.getCompanyID(), e);
            return DataResultEnum.ERROR.getValue();
        }

    }


    private static String generateRamdomNum() {
        String[] beforeShuffle = new String[]{"0", "1", "2", "3", "4", "5",
                "6", "7", "8", "9"};
        List<String> list = Arrays.asList(beforeShuffle);
        Collections.shuffle(list);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            sb.append(list.get(i));
        }
        String afterShuffle = sb.toString();
        String result = afterShuffle.substring(3, 7);
        return result;
    }


    public Map<String, String> getCode(String mobile) throws Exception {
        String t = (String) redisTemplate.opsForValue().get(mobile);
        Map<String, String> result = new HashMap<String, String>();
        result.put(mobile, t);
        return result;
    }


    @Async
    public void saveSms(AlibabaAliqinFcSmsNumSendRequest req, Integer type) {
        SmsCommont sms = new SmsCommont();
        Long id = IdGen.get().nextId();
        sms.setId(id);
        sms.setType(type);
        sms.setAddTime(System.currentTimeMillis());
        sms.setCompanyID(SystemContext.getCompanyID());
        sms.setSmsTemplateCode(req.getSmsTemplateCode());
        sms.setSmsFreeSignName(req.getSmsFreeSignName());
        sms.setMobile(req.getRecNum());
        sms.setParam(req.getSmsParam());
        log.info("profile={}", sms);
        commentRepository.save(sms);
        //return id;
    }

    public Object querySms(Map<String, String> params) {
        BasicDBList andList = new BasicDBList();
        if (CommonUtils.isNotEmpty(params.get("companyID"))) {
            andList.add(new BasicDBObject("companyID", Long.parseLong(params.get("companyID"))));
        }
        if (CommonUtils.isNotEmpty(params.get("type"))) {
            andList.add(new BasicDBObject("type", Integer.parseInt(params.get("type"))));
        }
        if (CommonUtils.isNotEmpty(params.get("mobile"))) {
            andList.add(new BasicDBObject("mobile", params.get("mobile")));
        }
        if (CommonUtils.isNotEmpty(params.get("smsTemplateCode"))) {
            andList.add(new BasicDBObject("smsTemplateCode", params.get("smsTemplateCode")));
        }
        if (CommonUtils.isNotEmpty(params.get("smsFreeSignName"))) {
            andList.add(new BasicDBObject("smsFreeSignName", params.get("smsFreeSignName")));
        }
        if (CommonUtils.isNotEmpty(params.get("beginTime"))) {
            andList.add(new BasicDBObject("addTime", new BasicDBObject("$gte", Long.parseLong(params.get("beginTime")))));
        }
        if (CommonUtils.isNotEmpty(params.get("endTime"))) {
            andList.add(new BasicDBObject("addTime", new BasicDBObject("$lte", Long.parseLong(params.get("endTime")))));
        }
        BasicDBObject andObj = new BasicDBObject("$and", andList);
        BasicQuery query = new BasicQuery(andObj);
        long totalCount = this.mongoTemplate.count(query, SmsCommont.class);
        int skip = (Integer.parseInt(params.get("pageIndex"))) * Integer.parseInt(params.get("pageSize"));
        //排序
        String sortField = params.get("sortField");
        String sortOrder = params.get("sortOrder");
        if (CommonUtils.isNotEmpty(sortField) && CommonUtils.isNotEmpty(sortOrder)) {
            if (sortOrder.equalsIgnoreCase("desc")) {
                query.with(new Sort(Sort.Direction.DESC, sortField));
            } else if (sortOrder.equalsIgnoreCase("asc")) {
                query.with(new Sort(Sort.Direction.ASC, sortField));
            }
        } else {
            query.with(new Sort(Sort.Direction.DESC, "addTime"));
        }
        List<SmsCommont> smsList = mongoTemplate.find(query.skip(skip).limit(Integer.parseInt(params.get("pageSize"))), SmsCommont.class);
        HashMap result = new HashMap();
        result.put("data", smsList);
        result.put("total", totalCount);
        return result;
    }


}
